import cv
import numpy

"""
" This function will display the given image file according to appropriate image type (color or grayscale)
"""
def displayImage(filename, image_type):
    try:
        if image_type == 'color':
            load_image = cv.LoadImageM(filename, cv.CV_LOAD_IMAGE_COLOR)
        elif image_type == 'gray':
            load_image = cv.LoadImageM(filename, cv.CV_LOAD_IMAGE_GRAYSCALE)
        else:
            load_image = cv.LoadImageM(filename, cv.CV_LOAD_IMAGE_UNCHANGED)
    except:
        print 'Issue in loading the image'
    else:
        cv.NamedWindow("Display window", cv.CV_WINDOW_NORMAL)
        cv.ShowImage("Display window", load_image)
        cv.WaitKey(0)
    return

"""
" This function will apply a simple linear filter on the given image file 
"""
def applyFilter(filename):
    try:
        original_image = cv.LoadImageM(filename)
    except:
        print 'Issue in loading the image'
    else:
        kernel = cv.CreateMat(3, 3, cv.CV_32FC1)
        cv.Set(kernel, 0)
        kernel[0,1] -= 1
        kernel[1,0] -= 1
        kernel[1,2] -= 1
        kernel[2,1] -= 1
        kernel[1,1] += 5
        new_image = cv.CreateMat(original_image.rows, original_image.cols, cv.CV_8UC3)
        cv.Filter2D(original_image,new_image,kernel)
        cv.NamedWindow("Original Image", cv.CV_WINDOW_NORMAL)
        cv.NamedWindow("New Image", cv.CV_WINDOW_NORMAL)
        cv.ShowImage("Original Image", original_image)
        cv.ShowImage("New Image", new_image)
        cv.WaitKey(0)
    return

"""
" This function will output weighted summation of two images
"""
def blendImages(file_one, file_two, alpha):
    try:
        image_one = cv.LoadImageM(file_one)
        image_two = cv.LoadImageM(file_two)
    except:
        print 'Issue in loading the image'
    else:
        new_image = cv.CreateMat(image_one.rows, image_one.cols, cv.CV_8UC3)
        cv.AddWeighted(image_one, alpha, image_two, (1.0 - alpha), 0.0, new_image) 
        cv.NamedWindow("Linear Blend", cv.CV_WINDOW_NORMAL)
        cv.ShowImage("Linear Blend", new_image)
        cv.WaitKey(0)
    return

"""
" This function will output gaussian smoothed image
"""
def smoothImage(filename):
    try:
        original_image = cv.LoadImageM(filename)
    except:
        print 'Issue in loading the image'
    else:
        new_image = cv.CloneMat(original_image)
        cv.Smooth(original_image,new_image,cv.CV_GAUSSIAN,5,5)
        cv.NamedWindow("Original Image", cv.CV_WINDOW_NORMAL)
        cv.NamedWindow("New Image", cv.CV_WINDOW_NORMAL)
        cv.ShowImage("Original Image", original_image)
        cv.ShowImage("New Image", new_image)
        cv.WaitKey(0)
    return

"""
" This function will illustrate image pyramid operations
"""
def imagePyramids(filename):
    print 'Zoom In-Out demo'
    print '* [u] -> Zoom in'
    print '* [d] -> Zoom out'
    print '* [ESC] -> Close program'
    try:
        original_image = cv.LoadImageM(filename)
        temporary_image = original_image
        destination_image = temporary_image
    except:
        print 'Issue in loading the image'
    else:
        cv.NamedWindow("Pyramids Demo", cv.CV_WINDOW_AUTOSIZE)
        cv.ShowImage("Pyramids Demo", destination_image)
        while True:
            c = cv.WaitKey(10)
            if c == 27:
                break
            elif c == 117:
                destination_image = cv.CreateMat(temporary_image.rows * 2, temporary_image.cols * 2, cv.CV_8UC3)
                cv.PyrUp(temporary_image,destination_image)
                print '** Zoom In: Image x 2'
            elif c == 100:
                destination_image = cv.CreateMat(temporary_image.rows / 2, temporary_image.cols / 2, cv.CV_8UC3)
                cv.PyrDown(temporary_image,destination_image)
                print '** Zoom Out: Image / 2'
            cv.ShowImage("Pyramids Demo", destination_image)
            temporary_image = destination_image
    return

"""
" This function will output absolute values of the derivatives of the image
"""
def sobelDerivatives(filename):
    try:
        original_image = cv.LoadImageM(filename, cv.CV_LOAD_IMAGE_GRAYSCALE)
    except:
        print 'Issue in loading the image'
    else:
        cv.Smooth(original_image,original_image,cv.CV_GAUSSIAN,5,5)
        grad = cv.CreateMat(original_image.rows, original_image.cols, cv.CV_8UC1)
        grad_x = cv.CreateMat(original_image.rows, original_image.cols, cv.CV_16SC1)
        grad_y = cv.CreateMat(original_image.rows, original_image.cols, cv.CV_16SC1)
        abs_grad_x = cv.CreateMat(original_image.rows, original_image.cols, cv.CV_8UC1)
        abs_grad_y = cv.CreateMat(original_image.rows, original_image.cols, cv.CV_8UC1)
        
        cv.Sobel(original_image,grad_x,1,0,3)
        cv.Sobel(original_image,grad_y,0,1,3)
        cv.ConvertScaleAbs(grad_x,abs_grad_x)
        cv.ConvertScaleAbs(grad_y,abs_grad_y)

        cv.AddWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0.0, grad) 
        
        cv.NamedWindow("Sobel Derivatives", cv.CV_WINDOW_NORMAL)
        cv.ShowImage("Sobel Derivatives", grad)
        cv.WaitKey(0)
    return


# Test - 01
#filename = raw_input("Name of the image file: ")
#image_type = raw_input("Image type (gray/color): ")
#displayImage(filename, image_type)

# Test - 02
#filename = raw_input("Name of the image file: ")
#applyFilter(filename)
 
# Test - 03
#blendImages('images_1.jpg', 'images_2.jpg', 0.5)

# Test - 04
#smoothImage('lena.png')

# Test - 05
#imagePyramids('lena.png')

# Test - 06
#sobelDerivatives('lena.png')





